# coding=utf-8
import backtrader as bt
import datetime

import pandas as pd

# 数据准备 300ETF 日级别数据
dataframe = pd.DataFrame()
for i in range(7):
    df = pd.read_csv('hist_data/510300_D_{}.csv'.format(2013 + i), parse_dates=True, index_col=0)
    dataframe = pd.concat([dataframe, df])


class SingleSMAStrategy(bt.Strategy):
    params = (('maperiod', 15),)

    def __init__(self):
        # Add a MovingAverageSimple indicator
        self.sma = bt.indicators.MovingAverageSimple(
            self.data0.close, period=self.p.maperiod)

        self.crossover = bt.indicators.CrossOver(self.data0.close, self.sma, plot=False)
        # To keep track of pending orders
        self.order = None

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        if order.status in [order.Completed, order.Canceled, order.Margin, order.Rejected]:
            # Write down: no pending order
            self.order = None

    def next(self):
        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        # Check if we are in the market
        if not self.position:
            # Not yet ... we MIGHT BUY if ...
            if self.crossover[0] == 1:
                # Keep track of the created order to avoid a 2nd order
                self.order = self.buy()
        else:
            # Already in the market ... we might sell
            if self.crossover[0] == -1:
                # Keep track of the created order to avoid a 2nd order
                self.order = self.sell()

    def stop(self):
        print('(MA Period {:2d}) Ending Value {:.2f}'.format(
            self.params.maperiod, self.broker.getvalue()))


cerebro = bt.Cerebro()

# pandasdata feeder
df_feeder = bt.feeds.PandasData(dataname=dataframe, openinterest=None)

cerebro.adddata(df_feeder, name='etf300')

# cerebro.addstrategy(SingleSMAStrategy, maperiod=18)
cerebro.optstrategy(SingleSMAStrategy, maperiod=range(15, 91))

# 小场面1万起始资金
cerebro.broker.setcash(10000.0)

# 手续费万5
cerebro.broker.setcommission(0.0005)

# 以发出信号当日收盘价成交
cerebro.broker.set_coc(True)

# Add a FixedSize sizer according to the stake
cerebro.addsizer(bt.sizers.AllInSizerInt, percents=99)

print('Starting Portfolio Value: {:.2f}'.format(cerebro.broker.getvalue()))

cerebro.addanalyzer(bt.analyzers.AnnualReturn)
cerebro.addanalyzer(bt.analyzers.TimeDrawDown)
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer)
cerebro.addanalyzer(bt.analyzers.SQN)

result = cerebro.run()
